package jdec.jdt.ls.decompiler.common;

import java.net.URI;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences;


public abstract class CachingDecompiler {

    protected Cache<String, String> classSourceCache =
            CacheBuilder.newBuilder().maximumSize(5_000_000).build();

    public String getContent(URI uri, IProgressMonitor monitor) throws CoreException {
        String cacheKey = uri.toString();
        String content = classSourceCache.getIfPresent(cacheKey);
        if (content == null) {
            content = decompileContent(uri, monitor);
        }
        boolean enableCache = JavaDecompilerPlugin.getDefault().isEnableCache();
        if (content != null && enableCache) {
            classSourceCache.put(cacheKey, content);
        }
        return content;
    }

    // IOrdinaryClassFile classFile
    public String getSource(IType type, IProgressMonitor monitor) throws CoreException {
        IClassFile classFile = type.getClassFile();
        String cacheKey = classFile.getHandleIdentifier();
        String content = classSourceCache.getIfPresent(cacheKey);
        if (content == null) {
            content = decompileContent(type, monitor);
        }
        boolean enableCache = JavaDecompilerPlugin.getDefault().isEnableCache();
        if (content != null && enableCache) {
            classSourceCache.put(cacheKey, content);
        }
        return content;
    }

    protected abstract String decompileContent(URI uri, IProgressMonitor monitor)
            throws CoreException;

    protected abstract String decompileContent(IType type, IProgressMonitor monitor)
            throws CoreException;

    protected abstract String decompileFromArchive(String archivePath, String packege,
            String className, IProgressMonitor monitor) throws CoreException;

    protected abstract String getDecompilerType();

    protected abstract void setDecompilePreferences(Preferences preferences);
}
